package com.example.comsys.util;

import com.example.comsys.dataobject.AdminDO;
import com.example.comsys.dataobject.AttendDO;
import com.example.comsys.dataobject.DepartmentDO;
import com.example.comsys.dataobject.EmployeeDO;
import com.example.comsys.dataobject.WageDO;
import com.example.comsys.model.Admin;
import com.example.comsys.model.Attend;
import com.example.comsys.model.Department;
import com.example.comsys.model.Employee;
import com.example.comsys.model.Wage;
import com.example.comsys.model.WorkState;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import org.springframework.beans.BeanUtils;

/**
 * do and dto conversion utils
 *
 * @author wjh
 * @date 2019/12/30, 周一
 */
public class ConvertUtils {


  public static class AdminUtils {

    public static AdminDO adminToDO(Admin admin) {
      if (admin != null && admin.getId() != null) {
        AdminDO adminDO = new AdminDO();
        BeanUtils.copyProperties(admin, adminDO);

        return adminDO;
      }
      return null;
    }

    public static Admin adminToModel(AdminDO adminDO) {
      if (adminDO != null && adminDO.getId() != null) {
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminDO, admin);
        admin.setGmtCreated(dateToLocalDateTime(adminDO.getGmtCreated()));
        admin.setGmtModified(dateToLocalDateTime(adminDO.getGmtModified()));
        return admin;
      }
      return null;
    }
  }

  public static class EmployeeUtils {

    public static Employee employeeToModel(EmployeeDO employeeDO) {
      if (employeeDO == null || employeeDO.getEmployeeId() <= 0) {
        return null;
      }

      Employee employee = new Employee();
      BeanUtils.copyProperties(employeeDO, employee);
      // add department
      Department department = new Department();
      department.setDepartId(employeeDO.getDepartId());
      employee.setDepartment(department);

      employee.setState(WorkState.valueOf(employeeDO.getState()));
      employee.setGmtCreated(dateToLocalDateTime(employeeDO.getGmtCreated()));
      employee.setGmtModified(dateToLocalDateTime(employeeDO.getGmtModified()));
      return employee;
    }

    public static EmployeeDO employeeToDO(Employee employee) {
      if (employee == null) {
        return null;
      }
      if (employee.getDepartment() == null || employee.getDepartment().getDepartId() <= 0) {
        return null;
      }

      EmployeeDO employeeDO = new EmployeeDO();
      BeanUtils.copyProperties(employee, employeeDO);
      // set department id
      employeeDO.setDepartId(employee.getDepartment().getDepartId());
      employeeDO.setState(employee.getState().name());

      employeeDO.setGmtCreated(localDateTimeToDate(employee.getGmtCreated()));
      employeeDO.setGmtModified(localDateTimeToDate(employee.getGmtModified()));
      return employeeDO;
    }
  }

  public static class DepartmentUtils {

    public static Department departmentToModel(DepartmentDO departmentDO) {
      if (departmentDO == null || departmentDO.getDepartId() == null) {
        return null;
      }

      Department department = new Department();
      BeanUtils.copyProperties(departmentDO, department);
      department.setGmtCreated(dateToLocalDateTime(departmentDO.getGmtCreated()));
      department.setGmtModified(dateToLocalDateTime(departmentDO.getGmtModified()));
      return department;
    }
  }

  public static class AttendUtils {

    public static Attend attendToModel(AttendDO attendDO) {
      if (attendDO == null || attendDO.getEmployeeId() == null) {
        return null;
      }
      Attend attend = new Attend();
      BeanUtils.copyProperties(attendDO, attend);
      attend.setDate(dateToLocalDate(attendDO.getDate()));
      attend.setGmtCreated(dateToLocalDateTime(attendDO.getGmtCreated()));
      attend.setGmtModified(dateToLocalDateTime(attendDO.getGmtModified()));
      return attend;
    }

    public static AttendDO attendToDO(Attend attend) {
      if (attend == null || attend.getEmployeeId() <= 0) {
        return null;
      }
      AttendDO attendDO = new AttendDO();
      BeanUtils.copyProperties(attend, attendDO);
      attendDO.setDate(localDateToDate(attend.getDate()));
      attendDO.setGmtCreated(localDateTimeToDate(attend.getGmtCreated()));
      attendDO.setGmtModified(localDateTimeToDate(attend.getGmtModified()));
      return attendDO;
    }
  }

  public static class WageUtils {

    public static Wage wageToModel(WageDO wageDO) {
      if (wageDO == null || wageDO.getEmployeeId() == null || wageDO.getId() == null) {
        return null;
      }
      Wage wage = new Wage();
      BeanUtils.copyProperties(wageDO, wage);
      wage.setGmtCreated(dateToLocalDateTime(wageDO.getGmtCreated()));
      wage.setGmtModified(dateToLocalDateTime(wageDO.getGmtModified()));
      return wage;
    }

    public static WageDO wageToDO(Wage wage) {
      if (wage == null || wage.getEmployeeId() < 0) {
        return null;
      }
      WageDO wageDo = new WageDO();
      BeanUtils.copyProperties(wage, wageDo);
      wageDo.setGmtCreated(localDateTimeToDate(wage.getGmtCreated()));
      wageDo.setGmtModified(localDateTimeToDate(wage.getGmtModified()));
      return wageDo;
    }
  }


  private static LocalDateTime dateToLocalDateTime(Date date) {
    if (date == null) {
      return null;
    }
    return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
  }

  public static Date localDateTimeToDate(LocalDateTime ldt) {
    if (ldt == null) {
      return null;
    }
    return Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
  }

  private static LocalDate dateToLocalDate(Date date) {
    if (date == null) {
      return null;
    }
    return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
  }

  public static Date localDateToDate(LocalDate ldt) {
    if (ldt == null) {
      return null;
    }
    LocalDateTime of = LocalDateTime.of(ldt, LocalTime.now());
    return Date.from(of.atZone(ZoneId.systemDefault()).toInstant());
  }

  public static Date localDateToDate(LocalDate ldt, boolean limitStartTime) {
    if (ldt == null) {
      return null;
    }
    LocalDateTime of = LocalDateTime.of(ldt, limitStartTime ? LocalTime.of(0, 0, 0) : LocalTime.of(23, 59, 59));
    return Date.from(of.atZone(ZoneId.systemDefault()).toInstant());
  }

}
